﻿using System;
using PhiStore.Threading;

namespace PhiStore
{
    /// <summary>
    /// Singleton log!
    /// Log buffer size is 5000 entries
    /// </summary>
    public class Log
    {
        private static Log instance = null;
        private Channel<string> buffer;
        private ulong fullCount = 0;

        private object mutex = new object();

        private ulong beeps = 0;

        private Log()
        {
            buffer = new Channel<string>(5000);
        }

        /// <summary>
        /// Returns the singleton instance of the log
        /// </summary>
        /// <returns>The Log</returns>
        public static Log Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new Log();
                }
                return instance;
            }
        }

        /// <summary>
        /// Adds an entry to the log if it isn't full
        /// </summary>
        /// <param name="identifier">An identifier string (name/ip/PID ...)</param>
        /// <param name="entry">The entry to be added</param>
        public void AddLogEntry(string identifier, string entry)
        {
            lock (mutex)
            {
                if (!buffer.TrySend("[" + identifier + "@" + DateTime.Now.ToLongTimeString() + "] " + entry))
                    fullCount++;
            }
        }

        /// <summary>
        /// Reads an entry from the log if it isn't empty
        /// </summary>
        /// <returns>An entry or an empty string</returns>
        public string ReadLogEntry()
        {
            string result;
            lock (mutex)
            {
                buffer.TryReceive(out result);
            }
            return result;
        }

        /// <summary>
        /// Returns the number of log entries
        /// </summary>
        public int Count
        {
            get {
                lock (mutex)
                {
                    return buffer.Count;
                }
            }
        }

        /// <summary>
        /// A number dictating how many times a log message was lost due to a full log
        /// </summary>
        public ulong FullCount
        {
            get {
                lock (mutex)
                {
                    return this.fullCount;
                }
            }
        }

        /// <summary>
        /// Increments a counter
        /// </summary>
        public void Beep()
        {
            lock (mutex)
            {
                beeps++;
            }
        }

        /// <summary>
        /// The number of times the Beep-method is called
        /// </summary>
        /// <returns>No. of Beeps</returns>
        public ulong Beeps()
        {
            lock(mutex){
                return beeps;
            }
        }
    }
}
